package org.jiucheng.magpiebridge.manager.service.impl;

import java.io.Serializable;
import java.util.List;

import org.jiucheng.aop.Aop;
import org.jiucheng.ioc.annotation.Inject;
import org.jiucheng.ioc.annotation.Service;
import org.jiucheng.magpiebridge.manager.MangagerException;
import org.jiucheng.magpiebridge.manager.dto.ClientDto;
import org.jiucheng.magpiebridge.manager.entity.Client;
import org.jiucheng.magpiebridge.manager.entity.ClientMapping;
import org.jiucheng.magpiebridge.manager.entity.Server;
import org.jiucheng.magpiebridge.manager.entity.ServerResource;
import org.jiucheng.magpiebridge.manager.entity.ServerResourceRule;
import org.jiucheng.magpiebridge.manager.entity.SysUserServer;
import org.jiucheng.magpiebridge.manager.service.IClientService;
import org.jiucheng.magpiebridge.manager.util.ThreadArgs;
import org.jiucheng.orm.Sql;
import org.jiucheng.orm.interceptor.Tx;
import org.jiucheng.plugin.db.IBaseService;

@Service("clientService")
public class ClientServiceImpl implements IClientService {
    
    @Inject
    private IBaseService baseService;
    
    public void setBaseService(IBaseService baseService) {
        this.baseService = baseService;
    }

    public List<ClientDto> listClientDto(Long userId) {
        Sql sql = new Sql(" SELECT a.id, a.name, a.token, a.server_id, b.name server_name ");
        sql.append(" FROM client a LEFT JOIN server b ON a.server_id=b.id WHERE a.user_id=?");
        sql.insertValue(userId);
        return baseService.getBaseDao().listBySQL(ClientDto.class, sql);
    }
    
    @Aop(Tx.class)
    public void deleteClient(Long id) {
        
        Client del = new Client();
        del.setId(id);
        baseService.delete(del);
        
        ClientMapping clientMappingOfSearch = new ClientMapping();
        clientMappingOfSearch.setClientId(id);
        List<ClientMapping> clientMappings = baseService.list(clientMappingOfSearch);
        // baseService.delete(clientMapping);
        
        if (clientMappings != null && !clientMappings.isEmpty()) {
            for (ClientMapping cm : clientMappings) {
                ClientMapping delete = new ClientMapping();
                delete.setId(cm.getId());
                int cnt = baseService.delete(delete);
                if (cnt > 0) {
	            	if (cm.getServerId() != null) {
	                	if (!"TCP".equalsIgnoreCase(cm.getServerProtocol())) {
	                		updateSysUserServerCount(cm.getServerId(), null, -1L);
	                	} else {
	                		updateSysUserServerCount(cm.getServerId(), -1L, null);
	                	}
	            	}
                }
                ServerResource serverResource = new ServerResource();
                serverResource.setServerId(cm.getServerId());
                serverResource.setServerProtocol(cm.getServerProtocol());
                serverResource.setServerIpPort(cm.getServerIpPort());
                List<ServerResource> list = baseService.list(serverResource);
                if (list == null || list.isEmpty()) {
                    baseService.save(serverResource);
                }
            }
        }
    }
    
    public void deleteClients(List<Client> clients) {
        if (clients != null && !clients.isEmpty()) {
            for (Client client : clients) {
                if (client != null) {
                    deleteClient(client.getId());
                }
            }
        }
    }
    
    @Aop(Tx.class)
    public void deleteClientMappings(List<ClientMapping> clientMappings) {
        if (clientMappings != null && !clientMappings.isEmpty()) {
            for (ClientMapping clientMapping : clientMappings) {
                if (clientMapping != null) {
                    ClientMapping delete = new ClientMapping();
                    delete.setId(clientMapping.getId());
                    int cnt = baseService.delete(delete);
                    if (cnt > 0) {
                    	if (clientMapping.getServerId() != null) {
                        	if (!"TCP".equalsIgnoreCase(clientMapping.getServerProtocol())) {
                        		updateSysUserServerCount(clientMapping.getServerId(), null, -1L);
                        	} else {
                        		updateSysUserServerCount(clientMapping.getServerId(), -1L, null);
                        	}
                    	}
                    }
                    Server server = baseService.get(Server.class, clientMapping.getServerId());
                    if (server != null) {
                        // 回收
                        ServerResource serverResource = new ServerResource();
                        serverResource.setServerId(clientMapping.getServerId());
                        serverResource.setServerProtocol(clientMapping.getServerProtocol());
                        serverResource.setServerIpPort(clientMapping.getServerIpPort());
                        List<ServerResource> list = baseService.list(serverResource);
                        if (list == null || list.isEmpty()) {
                            baseService.save(serverResource);
                        }
                    }
                }
            }
        }
    }
    
    @Aop(Tx.class)
    public Serializable saveClientMappingAndUpdateServerResourceRule(ClientMapping clientMapping, ServerResourceRule serverResourceRule) {
    	if (!"TCP".equalsIgnoreCase(clientMapping.getServerProtocol())) {
    		updateSysUserServerCount(clientMapping.getServerId(), null, 1L);
    	} else {
    		updateSysUserServerCount(clientMapping.getServerId(), 1L, null);
    	}
    	if (serverResourceRule != null) {
			baseService.update(serverResourceRule);
		}
    	return baseService.save(clientMapping);
    }
    
    private void updateSysUserServerCount(Long serverId, Long portCnt, Long subCnt) {
    	if (portCnt != null || subCnt != null) {
	    	SysUserServer sysUserServerOfGlobal = getSysUserServerByServerId(0L);
	    	if (sysUserServerOfGlobal == null) {
	    		sysUserServerOfGlobal = new SysUserServer();
	    		sysUserServerOfGlobal.setPortCount(0L);
	    		sysUserServerOfGlobal.setPortCountLimit(-1L);
	    		sysUserServerOfGlobal.setServerId(0L);
	    		sysUserServerOfGlobal.setSubCount(0L);
	    		sysUserServerOfGlobal.setSubCountLimit(-1L);
	    		sysUserServerOfGlobal.setUserId(ThreadArgs.getGid());
	    		sysUserServerOfGlobal.setVer(0);
	    		Serializable id = baseService.save(sysUserServerOfGlobal);
	    		sysUserServerOfGlobal.setId((Long) id);
	    	} else {
	    		// 验证是否超标
	    		if (portCnt != null && portCnt > 0L) {
	    			if ( sysUserServerOfGlobal.getPortCountLimit() > -1L &&
	    					(sysUserServerOfGlobal.getPortCount() + portCnt) > sysUserServerOfGlobal.getPortCountLimit()) {
	    				throw new MangagerException(1, "超出TCP限制数");
	    			}
	    		}
	    		if (subCnt != null && subCnt > 0L) {
	    			if (sysUserServerOfGlobal.getSubCountLimit() > -1L
	    					&& (sysUserServerOfGlobal.getSubCount() + subCnt) > sysUserServerOfGlobal.getSubCountLimit()) {
	    				throw new MangagerException(2, "超出HTTP限制数");
	    			}
	    		}
	    	}
	    	SysUserServer sysUserServerOfServer = getSysUserServerByServerId(serverId);
	    	if (sysUserServerOfServer == null) {
	    		sysUserServerOfServer = new SysUserServer();
	    		sysUserServerOfServer.setPortCount(0L);
	    		sysUserServerOfServer.setPortCountLimit(-1L);
	    		sysUserServerOfServer.setServerId(serverId);
	    		sysUserServerOfServer.setSubCount(0L);
	    		sysUserServerOfServer.setSubCountLimit(-1L);
	    		sysUserServerOfServer.setUserId(ThreadArgs.getGid());
	    		sysUserServerOfServer.setVer(0);
	    		Serializable id = baseService.save(sysUserServerOfServer);
	    		sysUserServerOfServer.setId((Long) id);
	    	}
	    	if (subCnt != null) {
	    		sysUserServerOfGlobal.setSubCount(sysUserServerOfGlobal.getSubCount() + subCnt);
	    		sysUserServerOfServer.setSubCount(sysUserServerOfServer.getSubCount() + subCnt);
	    	}
    		if (portCnt != null) {
	    		sysUserServerOfGlobal.setPortCount(sysUserServerOfGlobal.getPortCount() + portCnt);
	    		sysUserServerOfServer.setPortCount(sysUserServerOfServer.getPortCount() + portCnt);
	    	}
	    	baseService.update(sysUserServerOfGlobal);
	    	baseService.update(sysUserServerOfServer);
    	}
    }
    
    private SysUserServer getSysUserServerByServerId(Long serverId) {
    	SysUserServer sysUserServerOfSearch = new SysUserServer();
    	sysUserServerOfSearch.setUserId(ThreadArgs.getGid());
    	sysUserServerOfSearch.setServerId(serverId);
    	List<SysUserServer> list = baseService.list(sysUserServerOfSearch);
    	if (list != null && !list.isEmpty()) {
    		return list.get(0);
    	}
    	return null;
    }
}
